home *** CD-ROM | disk | FTP | other *** search
/ PC World 2007 June / PCWorld_2007-06_cd.bin / v cisle / tclock / tclocklight-040702-3.exe / source / common / playfile.c < prev    next >
C/C++ Source or Header  |  2004-05-12  |  13KB  |  578 lines

  1. /*-------------------------------------------------------------
  2.   playfile.c : play sound file
  3.   (C) 1997-2003 Kazuto Sato
  4.   Please read readme.txt about the license.
  5.   
  6.   Written by Kazubon, Nanashi-san
  7. ---------------------------------------------------------------*/
  8.  
  9. #include "common.h"
  10.  
  11. /* Globals */
  12.  
  13. BOOL PlayFile(HWND hwnd, const char *fname, int loops);
  14. BOOL PlayFileCmdLine(HWND hwnd, const char *str);
  15. BOOL Player(HWND hwnd, const char *fname);
  16. void StopFile(void);
  17. void OnMCINotify(HWND hwnd, WPARAM wFlags, LONG lDevID);
  18. BOOL IsSoundFile(const char* fname);
  19. BOOL PauseResume(HWND hwnd);
  20. BOOL GetPlayingPosition(char *dst);
  21. BOOL PrevNextTrack(HWND hwnd, BOOL bNext);
  22. BOOL IsPrevNext(BOOL bNext);
  23. BOOL PlayMCI(HWND hwnd, const char *fname, int loops);
  24.  
  25. /* Statics */
  26.  
  27. static BOOL StartMCI(HWND hwnd);
  28. static BOOL PlayWave(HWND hwnd, const char *fname, int loops);
  29. static void StopWave(void);
  30.  
  31. static char *m_soundexts[] = { "wav", "mid", "cda", "mp3", "wma", "ogg", NULL };
  32.  
  33. // MCI
  34. static BOOL m_bMCIPlaying = FALSE;
  35. static int  m_countPlay = 0, m_numLoops = 0;
  36. static int  m_nTrack, m_nCDATrack;
  37. static BOOL m_bAudioCD;
  38. static BOOL m_bPausing = FALSE;
  39.  
  40. // WAV
  41. static WAVEFORMATEX *m_pWaveFormat = NULL;
  42. static HWAVEOUT m_hWaveOut = NULL;
  43. static HPSTR    m_pWaveData = NULL;
  44. static WAVEHDR  m_wh;
  45.  
  46. /* Externs */
  47.  
  48. /* exe/command.c , property/main.c
  49.   This function must exist in other source file */
  50. BOOL ExecCommandString(HWND hwnd, const char* command);
  51.  
  52. /*------------------------------------------------
  53.   play sound or open file
  54. --------------------------------------------------*/
  55. BOOL PlayFile(HWND hwnd, const char *fname, int loops)
  56. {
  57.     BOOL bMCIWave;
  58.     char fname2[MAX_PATH];
  59.     BOOL r;
  60.     
  61.     if(!fname || *fname == 0) return FALSE;
  62.     
  63.     bMCIWave = GetMyRegLong("", "MCIWave", FALSE);
  64.     
  65.     if(!bMCIWave && ext_cmp(fname, "wav") == 0)
  66.     {
  67.         if(m_bMCIPlaying || m_hWaveOut) return FALSE;
  68.         RelToAbs(fname2, fname);
  69.         r = PlayWave(hwnd, fname2, loops);
  70.         if(r) return r;
  71.     }
  72.     else if(IsSoundFile(fname))
  73.     {
  74.         if(m_bMCIPlaying || m_hWaveOut) return FALSE;
  75.         RelToAbs(fname2, fname);
  76.         r = PlayMCI(hwnd, fname2, loops);
  77.         if(r) return r;
  78.     }
  79.     
  80.     ExecCommandString(hwnd, fname);
  81.     return FALSE;
  82. }
  83.  
  84. /*------------------------------------------------
  85.   str: "3 sound.wav"
  86. --------------------------------------------------*/
  87. BOOL PlayFileCmdLine(HWND hwnd, const char *str)
  88. {
  89.     char fname[MAX_PATH];
  90.     const char *p = str;
  91.     int loops = 0;
  92.     int i;
  93.     
  94.     if(strncmp(p, "-1 ", 3) == 0)
  95.     {
  96.         loops = -1; p += 3;
  97.     }
  98.     else
  99.     {
  100.         while(*p)
  101.         {
  102.             if('0' <= *p && *p <= '9')
  103.                 loops = loops * 10 + (*p - '0');
  104.             else break;
  105.             p++;
  106.         }
  107.     }
  108.     while(*p == ' ') p++;
  109.     
  110.     for(i = 0; i < MAX_PATH-1 && *p; i++)
  111.         fname[i] = *p++;
  112.     fname[i] = 0;
  113.     
  114.     return PlayFile(hwnd, fname, loops);
  115. }
  116.  
  117. /*------------------------------------------------
  118.    stop playing sound
  119. --------------------------------------------------*/
  120. void StopFile(void)
  121. {
  122.     StopWave();
  123.     if(m_bMCIPlaying)
  124.     {
  125.         mciSendString("stop myfile", NULL, 0, NULL);
  126.         mciSendString("close myfile", NULL, 0, NULL);
  127.         m_bMCIPlaying = FALSE;
  128.         m_bPausing = FALSE;
  129.         m_countPlay = 0; m_numLoops = 0;
  130.     }
  131. }
  132.  
  133. /*------------------------------------------------
  134.    MM_MCINOTIFY message
  135. --------------------------------------------------*/
  136. void OnMCINotify(HWND hwnd, WPARAM wFlags, LONG lDevID)
  137. {
  138.     if(!m_bMCIPlaying) return;
  139.     
  140.     if(wFlags != MCI_NOTIFY_SUCCESSFUL && wFlags != MCI_NOTIFY_FAILURE)
  141.         return;
  142.     
  143.     if(wFlags == MCI_NOTIFY_SUCCESSFUL &&
  144.         (m_countPlay < m_numLoops || m_numLoops < 0))
  145.     {
  146.         mciSendString("seek myfile to start wait", NULL, 0, NULL);
  147.         if(StartMCI(hwnd))
  148.             m_countPlay++;
  149.         else
  150.             StopFile();
  151.     }
  152.     else StopFile();
  153. }
  154.  
  155. /*------------------------------------------------
  156.   Is CD-ROM ?
  157. --------------------------------------------------*/
  158. BOOL IsCDROM(const char *p)
  159. {
  160.     if((('A' <= *p && *p <= 'Z') || ('a' <= *p && *p <= 'z')) &&
  161.         *(p + 1) == ':' && 
  162.         (*(p + 2) == 0 || (*(p + 2) == '\\' && *(p + 3) == 0)))
  163.     {
  164.         char temp[10];
  165.         
  166.         temp[0] = p[0]; temp[1] = p[1];
  167.         temp[2] = '\\'; temp[3] = 0;
  168.         if(GetDriveType(temp) == DRIVE_CDROM) return TRUE;
  169.     }
  170.     
  171.     return FALSE;
  172. }
  173.  
  174. /*------------------------------------------------
  175.   Is sound file ?
  176. --------------------------------------------------*/
  177. BOOL IsSoundFile(const char* fname)
  178. {
  179.     int i;
  180.     
  181.     if(lstrcmpi(fname, "cdaudio") == 0) return TRUE;
  182.     
  183.     if(IsCDROM(fname)) return TRUE;
  184.     
  185.     for(i = 0; m_soundexts[i]; i++)
  186.     {
  187.         if(ext_cmp(fname, m_soundexts[i]) == 0)
  188.         {
  189.             return TRUE;
  190.         }
  191.     }
  192.     return FALSE;
  193. }
  194.  
  195. /*------------------------------------------------
  196.    Pause/Resume sound
  197. --------------------------------------------------*/
  198. BOOL PauseResume(HWND hwnd)
  199. {
  200.     if(m_bMCIPlaying)
  201.     {
  202.         int r;
  203.         
  204.         if(m_bPausing)
  205.         {
  206.             r = mciSendString("play myfile notify", NULL, 0, hwnd);
  207.             m_bPausing = FALSE;
  208.         }
  209.         else
  210.         {
  211.             r = mciSendString("pause myfile", NULL, 0, NULL);
  212.             m_bPausing = TRUE;
  213.         }
  214.         if(r == 0) return TRUE;
  215.     }
  216.     return FALSE;
  217. }
  218.  
  219. /*------------------------------------------------
  220.   get elapsed time string
  221. --------------------------------------------------*/
  222. BOOL GetPlayingPosition(char *dst)
  223. {
  224.     char retr[21], *p;
  225.     int sec;
  226.     
  227.     if(!m_bMCIPlaying) return FALSE;
  228.     
  229.     if(mciSendString("status myfile position", retr, 20, NULL) != 0)
  230.         return FALSE;
  231.     
  232.     if(m_bAudioCD) // 01:02:03:04 -> [01]:02:03
  233.     {
  234.         int c = 0;
  235.         
  236.         p = retr;
  237.         *dst++ = '[';
  238.         while(*p)
  239.         {
  240.             if(!('0' <= *p && *p <= '9'))
  241.             {
  242.                 if(c == 0) { *dst++ = ']'; p++; }
  243.                 else if(c == 1) { *dst++ = *p++; }
  244.                 else break;
  245.                 c++;
  246.             }
  247.             else *dst++ = *p++;
  248.         }
  249.         *dst = 0;
  250.     }
  251.     else
  252.     {
  253.         sec = atoi(retr) / 1000;
  254.         wsprintf(dst, "%02d:%02d", sec/60, sec%60);
  255.     }
  256.     return TRUE;
  257. }
  258.  
  259. /*------------------------------------------------
  260.    Previous/Next Track of Audio CD
  261. --------------------------------------------------*/
  262. BOOL PrevNextTrack(HWND hwnd, BOOL bNext)
  263. {
  264.     char retr[20], command[80];
  265.     int nTrack;
  266.     
  267.     if(! (m_bMCIPlaying && m_bAudioCD && !m_nCDATrack))
  268.         return FALSE;
  269.     
  270.     if(mciSendString("status myfile current track", retr, 20, NULL) != 0)
  271.         return FALSE;
  272.     
  273.     nTrack = atoi(retr);
  274.     if(bNext)
  275.     {
  276.         if(nTrack >= m_nTrack) return TRUE;
  277.         nTrack++;
  278.     }
  279.     else
  280.     {
  281.         if(nTrack < 2) return TRUE;
  282.         nTrack--;
  283.     }
  284.     wsprintf(command,
  285.         "play myfile from %02d:00:00:00 notify", nTrack);
  286.     if(mciSendString(command, NULL, 0, hwnd) == 0)
  287.         return TRUE;
  288.     return FALSE;
  289. }
  290.  
  291. /*------------------------------------------------
  292.   Prev/Next can be used?
  293. --------------------------------------------------*/
  294. BOOL IsPrevNext(BOOL bNext)
  295. {
  296.     char retr[20];
  297.     int nTrack;
  298.     
  299.     if(! (m_bMCIPlaying && m_bAudioCD && !m_nCDATrack))
  300.         return FALSE;
  301.     
  302.     if(mciSendString("status myfile current track", retr, 20, NULL) != 0)
  303.         return FALSE;
  304.     
  305.     nTrack = atoi(retr);
  306.     if(bNext)
  307.     {
  308.         if(nTrack >= m_nTrack) return FALSE;
  309.     }
  310.     else
  311.     {
  312.         if(nTrack < 2) return FALSE;
  313.     }
  314.     return TRUE;
  315. }
  316.  
  317. /*------------------------------------------------
  318.   create a string:  "*.wav;*.mid; ...."
  319. --------------------------------------------------*/
  320. void GetSoundFileExts(char* dst)
  321. {
  322.     char *dp;
  323.     int i;
  324.     
  325.     dp = dst;
  326.     for(i = 0; m_soundexts[i]; i++)
  327.     {
  328.         if(dp != dst) *dp++ = ';';
  329.         *dp++ = '*'; *dp++ = '.';
  330.         strcpy(dp, m_soundexts[i]);
  331.         dp += strlen(dp);
  332.     }
  333.     *dp = 0;
  334. }
  335.  
  336. /*------------------------------------------------
  337.   open MCI file and play
  338. --------------------------------------------------*/
  339. BOOL PlayMCI(HWND hwnd, const char *fname, int loops)
  340. {
  341.     char command[MAX_PATH+30], retr[80];
  342.     BOOL bCDROM;
  343.     
  344.     if(ext_cmp(fname, "ogg") == 0)
  345.         WriteProfileString("MCI Extensions", "ogg", "MPEGVideo");
  346.     
  347.     bCDROM = IsCDROM(fname);
  348.     
  349.     strcpy(command, "open \"");
  350.     strcat(command, fname);
  351.     if(bCDROM && command[strlen(command)-1] == '\\')
  352.          command[strlen(command)-1] = 0;
  353.     strcat(command, "\"");
  354.     if(bCDROM) strcat(command, " type cdaudio");
  355.     strcat(command, " alias myfile");
  356.     
  357.     if(mciSendString(command, NULL, 0, NULL) != 0) return FALSE;
  358.     
  359.     m_bAudioCD = FALSE;
  360.     if(lstrcmpi(fname, "cdaudio") == 0 || bCDROM ||
  361.         ext_cmp(fname, "cda") == 0)
  362.         m_bAudioCD = TRUE;
  363.     
  364.     strcpy(command, "set myfile time format ");
  365.     if(m_bAudioCD)
  366.         strcat(command, "tmsf");
  367.     else
  368.         strcat(command, "milliseconds");
  369.     mciSendString(command, NULL, 0, NULL);
  370.     
  371.     m_nTrack = 1;
  372.     if(m_bAudioCD)
  373.     {
  374.         if(mciSendString("status myfile number of tracks",
  375.             retr, 80, NULL) == 0)
  376.                 m_nTrack = atoi(retr);
  377.     }
  378.     
  379.     m_nCDATrack = 0;
  380.     if(ext_cmp(fname, "cda") == 0)
  381.     {
  382.         const char* p = fname;
  383.         while(*p)
  384.         {
  385.             if('0' <= *p && *p <= '9')
  386.                 m_nCDATrack = m_nCDATrack * 10 + *p - '0';
  387.             p++;
  388.         }
  389.     }
  390.     
  391.     if(StartMCI(hwnd))
  392.     {
  393.         m_bMCIPlaying = TRUE;
  394.         m_countPlay = 1; m_numLoops = loops;
  395.     }
  396.     else
  397.     {
  398.         mciSendString("close myfile", NULL, 0, NULL);
  399.     }
  400.     
  401.     return m_bMCIPlaying;
  402. }
  403.  
  404. /*------------------------------------------------
  405.    play MCI file
  406. --------------------------------------------------*/
  407. BOOL StartMCI(HWND hwnd)
  408. {
  409.     char command[80];
  410.     
  411.     strcpy(command, "play myfile");
  412.     if(m_nCDATrack > 0)
  413.     {
  414.         wsprintf(command + strlen(command), " from %02d:00:00:00",
  415.             m_nCDATrack);
  416.         if(m_nCDATrack < m_nTrack)
  417.             wsprintf(command + strlen(command), " to %02d:00:00:00",
  418.                 m_nCDATrack+1);
  419.     }
  420.     strcat(command, " notify");
  421.     
  422.     if(mciSendString(command, NULL, 0, hwnd) == 0) return TRUE;
  423.     return FALSE;
  424. }
  425.  
  426. /*------------------------------------------------
  427.   Play WAV
  428. --------------------------------------------------*/
  429. BOOL PlayWave(HWND hwnd, const char *fname, int loops)
  430. {
  431.     HMMIO hmmio;
  432.     MMCKINFO mmckinfoParent;
  433.     MMCKINFO mmckinfoSubchunk;
  434.     LONG lFmtSize;
  435.     LONG lDataSize;
  436.     
  437.     if(m_hWaveOut != NULL) return FALSE;
  438.     
  439.     hmmio = mmioOpen((LPSTR)fname, NULL, MMIO_READ | MMIO_ALLOCBUF);
  440.     if(!hmmio) return FALSE;
  441.     
  442.     mmckinfoParent.fccType = mmioFOURCC('W', 'A', 'V', 'E');
  443.     if(mmioDescend(hmmio, (LPMMCKINFO) &mmckinfoParent, NULL, MMIO_FINDRIFF))
  444.     {
  445.         mmioClose(hmmio, 0);
  446.         return FALSE;
  447.     }
  448.     
  449.     mmckinfoSubchunk.ckid = mmioFOURCC('f', 'm', 't', ' ');
  450.     if(mmioDescend(hmmio, &mmckinfoSubchunk, &mmckinfoParent,
  451.         MMIO_FINDCHUNK))
  452.     {
  453.         mmioClose(hmmio, 0);
  454.         return FALSE;
  455.     }
  456.     
  457.     lFmtSize = mmckinfoSubchunk.cksize;
  458.     m_pWaveFormat = (WAVEFORMATEX*)malloc(lFmtSize);
  459.     if(m_pWaveFormat == NULL)
  460.     {
  461.         mmioClose(hmmio, 0);
  462.         return FALSE;
  463.     }
  464.     
  465.     if(mmioRead(hmmio, (HPSTR)m_pWaveFormat, lFmtSize) != lFmtSize)
  466.     {
  467.         free(m_pWaveFormat); m_pWaveFormat = NULL;
  468.         mmioClose(hmmio, 0);
  469.         return FALSE;
  470.     }
  471.     
  472.     /*
  473.     if(m_pWaveFormat->wFormatTag != WAVE_FORMAT_PCM)
  474.     {
  475.         free(m_pWaveFormat); m_pWaveFormat = NULL;
  476.         mmioClose(hmmio, 0);
  477.         return FALSE;
  478.     }
  479.     */
  480.  
  481.     if(waveOutOpen(&m_hWaveOut, (UINT)WAVE_MAPPER,
  482.         (LPWAVEFORMATEX)m_pWaveFormat,
  483.         0, 0, (DWORD)WAVE_FORMAT_QUERY))
  484.     {
  485.         free(m_pWaveFormat); m_pWaveFormat = NULL;
  486.         mmioClose(hmmio, 0);
  487.         return FALSE;
  488.     }
  489.     
  490.     mmioAscend(hmmio, &mmckinfoSubchunk, 0);
  491.     
  492.     mmckinfoSubchunk.ckid = mmioFOURCC('d', 'a', 't', 'a');
  493.     if(mmioDescend(hmmio, &mmckinfoSubchunk, &mmckinfoParent,
  494.         MMIO_FINDCHUNK))
  495.     {
  496.         free(m_pWaveFormat); m_pWaveFormat = NULL;
  497.         mmioClose(hmmio, 0);
  498.         return FALSE;
  499.     }
  500.     
  501.     lDataSize = mmckinfoSubchunk.cksize;
  502.     if(lDataSize == 0)
  503.     {
  504.         free(m_pWaveFormat); m_pWaveFormat = NULL;
  505.         mmioClose(hmmio, 0);
  506.         return FALSE;
  507.     }
  508.     
  509.     m_pWaveData = (HPSTR)malloc(lDataSize);
  510.     if(m_pWaveData == NULL)
  511.     {
  512.         free(m_pWaveFormat); m_pWaveFormat = NULL;
  513.         mmioClose(hmmio, 0);
  514.         return FALSE;
  515.     }
  516.     
  517.     if(mmioRead(hmmio, m_pWaveData, lDataSize) != lDataSize)
  518.     {
  519.         free(m_pWaveFormat); m_pWaveFormat = NULL;
  520.         free(m_pWaveData); m_pWaveData = NULL;
  521.         mmioClose(hmmio, 0);
  522.         return FALSE;
  523.     }
  524.     mmioClose(hmmio, 0);
  525.     
  526.     if(waveOutOpen((LPHWAVEOUT)&m_hWaveOut, (UINT)WAVE_MAPPER,
  527.         (LPWAVEFORMATEX)m_pWaveFormat, (UINT)hwnd, 0,
  528.         (DWORD)CALLBACK_WINDOW))
  529.     {
  530.         free(m_pWaveFormat); m_pWaveFormat = NULL;
  531.         free(m_pWaveData); m_pWaveData = NULL;
  532.         return FALSE;
  533.     }
  534.     
  535.     memset(&m_wh, 0, sizeof(WAVEHDR));
  536.     m_wh.lpData = m_pWaveData;
  537.     m_wh.dwBufferLength = lDataSize;
  538.     if(loops != 0)
  539.     {
  540.         m_wh.dwFlags = WHDR_BEGINLOOP|WHDR_ENDLOOP;
  541.         m_wh.dwLoops = (DWORD)loops;
  542.     }
  543.     if(waveOutPrepareHeader(m_hWaveOut, &m_wh, sizeof(WAVEHDR)))
  544.     {
  545.         waveOutClose(m_hWaveOut); m_hWaveOut = NULL;
  546.         free(m_pWaveFormat); m_pWaveFormat = NULL;
  547.         free(m_pWaveData); m_pWaveData = NULL;
  548.         return FALSE;
  549.     }
  550.     
  551.     if(waveOutWrite(m_hWaveOut, &m_wh, sizeof(WAVEHDR)) != 0)
  552.     {
  553.         waveOutUnprepareHeader(m_hWaveOut, &m_wh, sizeof(WAVEHDR));
  554.         waveOutClose(m_hWaveOut); m_hWaveOut = NULL;
  555.         free(m_pWaveFormat); m_pWaveFormat = NULL;
  556.         free(m_pWaveData); m_pWaveData = NULL;
  557.         return FALSE;
  558.     }
  559.     
  560.     return TRUE;
  561. }
  562.  
  563. /*------------------------------------------------
  564.   stop playing WAV
  565. --------------------------------------------------*/
  566. void StopWave(void)
  567. {
  568.     if(m_hWaveOut == NULL) return;
  569.     
  570.     waveOutReset(m_hWaveOut);
  571.     waveOutUnprepareHeader(m_hWaveOut, &m_wh, sizeof(WAVEHDR));
  572.     waveOutClose(m_hWaveOut);
  573.     m_hWaveOut = NULL;
  574.     free(m_pWaveFormat); m_pWaveFormat = NULL;
  575.     free(m_pWaveData); m_pWaveData = NULL;
  576. }
  577.  
  578.